#include "APIPersona.h"

APIPersona::APIPersona() {
	// Obtengo todos los IPCs dado que no sé cuales voy a utilizar
	
	this->semControl = Semaphore();
	this->semControl.getSemaphore((char *) DIRECTORY, ID_SEMCONTROL, 1);
	this->shMem = ControlDataSharedMemory();
	this->shMem.getSharedMemory((char *) DIRECTORY, ID_SHMEM);
	
	this->semTruckDoor = Semaphore();
	this->semTruckDoor.getSemaphore((char *) DIRECTORY, ID_SEMTRUCKDOOR, CANT_DOORS);

	// Obtención de colas para la comunicación con la puerta de la sala de Camiones
	this->truckDoorInputQueue = TruckDoorInputMessageQueue();
	this->truckDoorInputQueue.getMessageQueue((char *) DIRECTORY, ID_Q_TRUCK_DOOR_INPUT);
	this->truckDoorOutputQueue = TruckDoorOutputMessageQueue();
	this->truckDoorOutputQueue.getMessageQueue((char *) DIRECTORY, ID_Q_TRUCK_DOOR_OUTPUT);
	
	// Obtención de colas para la carga de personas al camión
	this->truckChargeInputQueue = TruckInputMessageQueue();
	this->truckChargeInputQueue.getMessageQueue((char *) DIRECTORY, ID_Q_TRUCK_CHARGE_INPUT);
	this->truckChargeOutputQueue = TruckOutputMessageQueue();
	this->truckChargeOutputQueue.getMessageQueue((char *) DIRECTORY, ID_Q_TRUCK_CHARGE_OUTPUT);
	
	// Obtención de colas para la descarga de personas al camión
	this->truckDischargeInputQueue = TruckInputMessageQueue();
	this->truckDischargeInputQueue.getMessageQueue((char *) DIRECTORY, ID_Q_TRUCK_DISCHARGE_INPUT);
	this->truckDischargeOutputQueue = TruckOutputMessageQueue();
	this->truckDischargeOutputQueue.getMessageQueue((char *) DIRECTORY, ID_Q_TRUCK_DISCHARGE_OUTPUT);
}

APIPersona::~APIPersona() {
}
	

void APIPersona::entrarASala(long idPersona, int nroPuerta, int *error) {
	TruckDoorInputMsg inputMsg;
	TruckDoorOutputMsg outputMsg;
	
	inputMsg.mtype = nroPuerta;
	inputMsg.idPersona = idPersona;
	
	sprintf(this->buffer, "Persona %ld: Envía mensaje a puertaCamion %d\n", idPersona, nroPuerta);
	write(fileno(stdout), buffer, strlen(buffer));
	this->truckDoorInputQueue.enviarMensaje(inputMsg);
	
	if (this->truckDoorOutputQueue.recibirMensaje(idPersona, &outputMsg) == -1) {
		// TODO: Capturar el errno y ver que pasó
		*error = ZIPC_FAILURE;
		return;
	}
	
	sprintf(this->buffer, "Persona %ld: Recibe mensaje de puertaCamion %d\n", idPersona, nroPuerta);
	write(fileno(stdout), buffer, strlen(buffer));
}
	
// 
void APIPersona::subirACamion(long idPersona, int *error) {
	TruckInputMsg inputMsg;
	TruckOutputMsg outputMsg;
	
	// Primero recibo el mensaje del camión de que la persona puede subir
	// al camión
	if (this->truckChargeOutputQueue.recibirMensaje(idPersona, &outputMsg) == -1) {
		*error = ZIPC_FAILURE;
		return;
	}
	
	#ifdef _DEBUG
	sprintf(this->buffer, "Persona %ld: Recibe mensaje de camion %d\n", idPersona, outputMsg.nroCamion);
	write(fileno(stdout), buffer, strlen(buffer));
	sprintf(this->buffer, "Persona %ld: Envía mensaje a camion %d\n", idPersona, outputMsg.nroCamion);
	write(fileno(stdout), buffer, strlen(buffer));
	#endif
	
	// Luego de recibir el mensaje, le aviso al camión que la persona ya subió
	inputMsg.mtype = outputMsg.nroCamion;
	if (this->truckChargeInputQueue.enviarMensaje(inputMsg) == -1) {
		*error = ZIPC_FAILURE;
		return;
	}
}

void APIPersona::bajarDeCamion(long idPersona, int *error) {
	TruckInputMsg inputMsg;
	TruckOutputMsg outputMsg;
	
	// Primero recibo el mensaje del camión de que la persona puede subir
	// al camión
	if (this->truckDischargeOutputQueue.recibirMensaje(idPersona, &outputMsg) == -1) {
		*error = ZIPC_FAILURE;
		return;
	}
	
	#ifdef _DEBUG
	sprintf(this->buffer, "Persona %ld: Recibe mensaje de camion %d\n", idPersona, outputMsg.nroCamion);
	write(fileno(stdout), buffer, strlen(buffer));
	sprintf(this->buffer, "Persona %ld: Envía mensaje a camion %d\n", idPersona, outputMsg.nroCamion);
	write(fileno(stdout), buffer, strlen(buffer));
	#endif
	
	inputMsg.mtype = outputMsg.nroCamion;
	if (this->truckDischargeInputQueue.enviarMensaje(inputMsg) == -1) {
		*error = ZIPC_FAILURE;
		return;
	}
}
